package com.assa.jco.server;

import java.util.List;

import com.assa.jco.dataprovider.DataProvider;
import com.assa.jco.handler.FunctionHandler;
import com.sap.conn.jco.JCoException;
import com.sap.conn.jco.ext.Environment;
import com.sap.conn.jco.server.DefaultServerHandlerFactory;
import com.sap.conn.jco.server.JCoServer;
import com.sap.conn.jco.server.JCoServerContextInfo;
import com.sap.conn.jco.server.JCoServerErrorListener;
import com.sap.conn.jco.server.JCoServerExceptionListener;
import com.sap.conn.jco.server.JCoServerFactory;
import com.sap.conn.jco.server.JCoServerState;
import com.sap.conn.jco.server.JCoServerStateChangedListener;

public class EventsJcoServer implements JCOServer {

	private String serverConfigurationName;	
	private List functionHandlers;
	private DataProvider dataProvider;
	
	public void setFunctionHandlers(List functionHandlers) {
		this.functionHandlers = functionHandlers;
	}

	public void setServerConfigurationName(String serverConfigurationName) {
		this.serverConfigurationName = serverConfigurationName;
	}

	

	public void setDataProvider(DataProvider dataProvider) {
		this.dataProvider = dataProvider;
	}


	public EventsJcoServer() {
	}
	

	private class MyThrowableListener implements JCoServerErrorListener, JCoServerExceptionListener {

		public void serverErrorOccurred(JCoServer jcoServer, String connectionId, JCoServerContextInfo serverCtx,
				Error error) {
			System.out.println(">>> Error occured on " + jcoServer.getProgramID() + " connection " + connectionId);
			error.printStackTrace();
		}

		public void serverExceptionOccurred(JCoServer jcoServer, String connectionId, JCoServerContextInfo serverCtx,
				Exception error) {
			System.out.println(">>> Error occured on " + jcoServer.getProgramID() + " connection " + connectionId);
			error.printStackTrace();
		}
	}

	private class MyStateChangedListener implements JCoServerStateChangedListener {
		public void serverStateChangeOccurred(JCoServer server, JCoServerState oldState, JCoServerState newState) {

			// Defined states are: STARTED, DEAD, ALIVE, STOPPED;
			// see JCoServerState class for details.
			// Details for connections managed by a server instance
			// are available via JCoServerMonitor
			System.out.println("Server state changed from " + oldState.toString() + " to " + newState.toString()
					+ " on server with program id " + server.getProgramID());
		}
	}

	private void runServer() {
		JCoServer server;
		try {
			server = JCoServerFactory.getServer(serverConfigurationName);
		} catch (JCoException ex) {
			throw new RuntimeException("Unable to create the server " + serverConfigurationName + ", because of "
					+ ex.getMessage(), ex);
		}

		server.setCallHandlerFactory(registerFunctionHandlers());

		// additionally to step 1
		MyThrowableListener eListener = new MyThrowableListener();
		server.addServerErrorListener(eListener);
		server.addServerExceptionListener(eListener);

		MyStateChangedListener slistener = new MyStateChangedListener();
		server.addServerStateChangedListener(slistener);

		server.start();
		System.out.println("The program can be stoped using <ctrl>+<c>");
	}


	private DefaultServerHandlerFactory.FunctionHandlerFactory registerFunctionHandlers() {
		DefaultServerHandlerFactory.FunctionHandlerFactory factory = new DefaultServerHandlerFactory.FunctionHandlerFactory();

		for(Object obj : this.functionHandlers) {
			FunctionHandler handler = (FunctionHandler) obj;
			factory.registerHandler(handler.getFunctionName(), handler);
			
		}
		
		return factory;
	}
	
	/* (non-Javadoc)
	 * @see com.assa.jco.server.JCOServer#starServer()
	 */
	public void starServer(){
		if(this.dataProvider != null) {
			Environment.registerDestinationDataProvider(this.dataProvider);
			Environment.registerServerDataProvider(this.dataProvider);
		}
		this.runServer();
	}
	

}
